
import random
from main import RootUnit, Unit


class DNA:

    connection = " & "

    def __repr__(self):
        dna = "-".join([str(i) for i in self.separations])
        dna += self.connection
        dna += "-".join([str(i) for i in self.structures])
        dna += self.connection
        dna += "-".join([str(i) for i in self.functions])
        return dna

    @classmethod
    def specific(cls, expression: str):
        new = cls(6, False)
        separation_str, structure_str, function_str = expression.split(cls.connection)
        new.separations = [int(i) for i in separation_str.split("-")]
        new.structures = [int(i) for i in structure_str.split("-")]
        new.functions = [int(i) for i in function_str.split("-")]
        return new

    @property
    def unit_length(self):
        return len(self.structures)

    def __init__(self, unit_length, initialize=True, random_range=1000):
        self.separations = []
        self.structures = []
        self.functions = [i for i in range(unit_length)]

        if initialize:
            self.separations = [
                random.randrange(random_range)
                for _ in range(unit_length - 1)
            ]
            self.structures = [
                random.randrange(random_range)
                for _ in range(unit_length - 1)
            ]
            random.shuffle(self.functions)


class Generator:
    def __init__(self, function_unit_length, width, height):
        self.function_unit_length = function_unit_length
        self.width = width
        self.height = height
        self.history:list[Unit] = []

    def generate_from_dna(self, dna: DNA):

        def get_separation_by_dna(dna_expression):
            denominator = self.function_unit_length * 10
            limit = denominator*0.3
            return (dna_expression % denominator) / (denominator + limit)

        is_row = dna.structures[0] % 2 == 1
        root = RootUnit(is_row, self.width, self.height)
        for index in range(self.function_unit_length - 1):
            separation = get_separation_by_dna(dna.separations[index])

            if index == 0:
                position = root
            else:
                length = root.unit_length
                index = dna.structures[index] % length
                position = root.unit_list()[index]

            position.separate(separation)

        # 为function unit添加function id
        for index, function_unit in enumerate(root.function_unit_list()):
            function_unit.function_id = dna.functions[index]

        return root

    def generate_from_random_dna(self) -> tuple[DNA, RootUnit]:

        def generate():
            dna = DNA(self.function_unit_length)
            root = self.generate_from_dna(dna)
            return dna, root

        while True:
            try:
                return generate()
            except ValueError:
                continue

def generate_grid(row:int, column:int, width:float, height:float):
    positions = []
    for y in range(column):
        for x in range(row):
            positions.append((x*width, y*height))
    return positions

if __name__ == '__main__':

    generator = Generator(6, 300, 150)

    dna_list = [
        "23-131-346-573-236 & 447-529-622-305-443 & 1-3-2-4-0-5",
        "137-507-276-102-741 & 751-995-398-169-581 & 4-1-3-2-0-5",
        "684-255-987-618-655 & 214-421-886-312-973 & 0-2-3-5-1-4",
        "692-974-798-425-278 & 403-238-684-307-83 & 1-4-0-5-3-2",
        "293-763-801-680-924 & 771-371-747-642-43 & 1-3-5-0-2-4",
        "197-116-995-753-216 & 497-534-819-637-348 & 3-0-4-2-1-5",
    ]

    colors = [
        "232,202,212,0",
        "186,125,141,0",
        "157,78,84,0",
        "163,210,226,0",
        "93,163,175,0",
        "16,135,148,0",
    ]

    positions = generate_grid(3, 2, 400, 250)

    macros = []
    for dna_str, position in zip(dna_list, positions):
        dna = DNA.specific(dna_str)
        root = generator.generate_from_dna(dna)
        macro = root.draw_in_rhino(
            show_function_id=True,
            shift=position,
            colors=colors,
            caption=dna_str,
            copy_into_clipboard=False
        )
        macros.append(macro)

    from pyperclip import copy
    copy("\n".join(macros))
